package com.bit.cfdi.web.services;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import com.bit.cfdi.web.dao.ComprobanteDAO;
import com.bit.cfdi.web.dao.UtilDAO;
import com.bit.cfdi.web.domain.Comprobante;
import com.bit.cfdi.web.domain.Negocio;
@Service
public class ComprobanteService {

	@Autowired
	private ComprobanteDAO comprobanteDAO;

	@Autowired
	private UtilDAO utilDAO;

	@Resource(name = "messageSource")
	private MessageSource messageSource;

	public HashMap<String, Double> getTotalPorClienteFecha(
			Long idCliente, Calendar fechaInicio, Calendar fechaFin, int tipo) throws DataAccessException { /*
		HashMap<String, Double> comprobanteMap = null;
		List<Comprobante> comprobateList = null;
		String key = null;
		SimpleDateFormat sfd = new SimpleDateFormat(SAFEConstants.DATE_FORMAT_DD_MM_YYYY);

		if (tipo == SAFEConstants.DIAGRAMA_HORAS) {
			comprobanteMap = new HashMap<String, Double>();
			comprobateList = comprobanteDAO.getTotalPorClienteFecha(idCliente, fechaInicio, fechaFin);

			if (null != comprobateList)
				for (Comprobante comprobante : comprobateList) {
					Calendar time = null!=comprobante.getFechaTimbrado()?comprobante.getFechaTimbrado()
							:comprobante.getFechaCreacion();
					key = String.valueOf(time.get(Calendar.HOUR_OF_DAY));
					double totalSuma = comprobante.getTotal() * (null!=comprobante.getTipoDeCambio()?comprobante.getTipoDeCambio():1);

					if (null != comprobanteMap.get(key)) {
						totalSuma = ((Double) comprobanteMap.get(key)).doubleValue();
						//DOLLAREMM
						totalSuma += comprobante.getTotal() * (null!=comprobante.getTipoDeCambio()?comprobante.getTipoDeCambio():1);
						comprobanteMap.remove(key);
					}

					comprobanteMap.put(key, totalSuma);
				}
		} else if (tipo == SAFEConstants.DIAGRAMA_DIAS) {
			comprobanteMap = new HashMap<String, Double>();
			comprobateList = comprobanteDAO.getTotalPorClienteFecha(idCliente, fechaInicio, fechaFin);

			if (null != comprobateList)
				for (Comprobante comprobante : comprobateList) {
					Calendar time = null!=comprobante.getFechaTimbrado()?comprobante.getFechaTimbrado()
							:comprobante.getFechaCreacion();
					int dayOfWeek = time.get(Calendar.DAY_OF_WEEK);

					if (dayOfWeek == Calendar.SUNDAY)
						key = "Domingo " + sfd.format(time.getTime());
					else if (dayOfWeek == Calendar.MONDAY)
						key = "Lunes " + sfd.format(time.getTime());
					else if (dayOfWeek == Calendar.TUESDAY)
						key = "Martes " + sfd.format(time.getTime());
					else if (dayOfWeek == Calendar.WEDNESDAY)
						key = "Miercoles " + sfd.format(time.getTime());
					else if (dayOfWeek == Calendar.THURSDAY)
						key = "Jueves " + sfd.format(time.getTime());
					else if (dayOfWeek == Calendar.FRIDAY)
						key = "Viernes " + sfd.format(time.getTime());
					else if (dayOfWeek == Calendar.SATURDAY) {
						key = "Sabado " + sfd.format(time.getTime());
					}

					double totalSuma = comprobante.getTotal() * (null!=comprobante.getTipoDeCambio()?comprobante.getTipoDeCambio():1);;

					if (null != comprobanteMap.get(key)) {
						totalSuma = ((Double) comprobanteMap.get(key)).doubleValue();
						//DOLLAREMM
						totalSuma += comprobante.getTotal() * (null!=comprobante.getTipoDeCambio()?comprobante.getTipoDeCambio():1);
						comprobanteMap.remove(key);
					}

					comprobanteMap.put(key, totalSuma);
				}
		} else if (tipo == SAFEConstants.DIAGRAMA_SEMANA) {
			comprobanteMap = new HashMap<String, Double>();
			Calendar endWeek = Calendar.getInstance();
			endWeek.setTime(fechaInicio.getTime());
			Calendar startWeek = Calendar.getInstance();
			startWeek.setTime(fechaInicio.getTime());
			int weekNumber = 1;

			while (fechaFin.compareTo(endWeek) > 0) {
				endWeek.add(Calendar.DATE, 6);

				setTime(startWeek, 0, 0, 0);
				setTime(endWeek, 23, 59, 59);

				key = "Semana " + String.valueOf(weekNumber);
				double totalSuma = comprobanteDAO.getSumTotalPorClienteFecha(idCliente, startWeek, endWeek);

				comprobanteMap.put(key, totalSuma);

				endWeek.add(Calendar.DATE, 1);
				startWeek.setTime(endWeek.getTime());

				weekNumber++;
			}

		} else if (tipo == SAFEConstants.DIAGRAMA_MES) {
			comprobanteMap = new HashMap<String, Double>();
			Calendar endDate = Calendar.getInstance();
			endDate.setTime(fechaInicio.getTime());
			Calendar startDate = Calendar.getInstance();
			startDate.setTime(fechaInicio.getTime());

			int start = Integer.parseInt(String.valueOf(fechaInicio.get(Calendar.YEAR))
					+ (fechaInicio.get(Calendar.MONTH) < 10 ? "0" + String.valueOf(fechaInicio.get(Calendar.MONTH)) : String
							.valueOf(fechaInicio.get(Calendar.MONTH))));
			int end = Integer.parseInt(String.valueOf(fechaFin.get(Calendar.YEAR))
					+ (fechaFin.get(Calendar.MONTH) < 10 ? "0" + String.valueOf(fechaFin.get(Calendar.MONTH)) : String
							.valueOf(fechaFin.get(Calendar.MONTH))));

			while (start <= end) {
				int dayMonth = startDate.getActualMinimum(Calendar.DAY_OF_MONTH);
				int daysMonth = startDate.getActualMaximum(Calendar.DAY_OF_MONTH);

				startDate.set(Calendar.DATE, dayMonth);
				endDate.set(Calendar.DATE, daysMonth);

				setTime(startDate, 0, 0, 0);
				setTime(endDate, 23, 59, 59);

				key = String.valueOf(startDate.get(Calendar.YEAR)) + " / "
						+ String.valueOf(SAFEUtils.formatString00(startDate.get(Calendar.MONTH) + 1));
				double totalSuma = comprobanteDAO.getSumTotalPorClienteFecha(idCliente, startDate, endDate);

				comprobanteMap.put(key, totalSuma);

				startDate.add(Calendar.MONTH, 1);
				endDate.add(Calendar.MONTH, 1);
				start = Integer.parseInt(String.valueOf(startDate.get(Calendar.YEAR))
						+ (startDate.get(Calendar.MONTH) < 10 ? "0" + String.valueOf(startDate.get(Calendar.MONTH)) : String
								.valueOf(startDate.get(Calendar.MONTH))));
			}

		}

		return comprobanteMap;*/
		return null;
	}

	public void saveChartClient(Object chart, String title, Long idCliente, int type) throws DataAccessException {/*
		JFreeChart graph = (JFreeChart) chart;
		String header = "", footer1 = "", footer2 = "", reportPath = "";
		String urlJar = System.getProperty("user.dir");
		JasperReport report;

		try {
			Map<String, Object> parameters = new HashMap<String, Object>();
			parameters.put("imageReport", graph.createBufferedImage(500, 257));
			parameters.put("idCliente", idCliente);
			parameters.put("title", title);
			parameters.put("type", type);
			header = messageSource.getMessage("cfdi.report.image.header.lin", null, LocationLanguage.getLocation());
			footer1 = messageSource.getMessage("cfdi.report.image.footer1.lin", null, LocationLanguage.getLocation());
			footer2 = messageSource.getMessage("cfdi.report.image.footer2.lin", null, LocationLanguage.getLocation());
			reportPath = messageSource.getMessage("path.report.cliente.lin", null, LocationLanguage.getLocation());

			parameters.put("headerReport", urlJar + header);
			parameters.put("footer1", urlJar + footer1);
			parameters.put("footer2", urlJar + footer2);			

			report = JasperCompileManager.compileReport(urlJar + reportPath);

			JasperPrint print = JasperFillManager.fillReport(report, parameters);

			JRViewer vw = new JRViewer(print, LocationLanguage.getLocation());
			JRSaveContributor[] saveTypeFile = vw.getSaveContributors();
			JRSaveContributor[] saveContribs = new JRSaveContributor[3];
			int i = 0;
			for (JRSaveContributor typeFile : saveTypeFile) {
				String tipo = typeFile.getDescription();

				if (tipo.contains("pdf") || tipo.contains("xls")) {
					saveContribs[i] = typeFile;
					i++;
				}
			}
			vw.setSaveContributors(saveContribs);

			URL url = getClass().getResource(messageSource.getMessage("img.icon.cfdiapp", null, LocationLanguage.getLocation()));
			JFrame j = new JFrame();
			j.getContentPane().add(vw, java.awt.BorderLayout.CENTER);
			j.setIconImage(new ImageIcon(url).getImage());
			j.setTitle(messageSource.getMessage("msg.title.report", null, LocationLanguage.getLocation()));

			j.pack();

			Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
			java.awt.Dimension screenSize = toolkit.getScreenSize();
			int screenResolution = toolkit.getScreenResolution();
			float zoom = ((float) screenResolution) / 72;

			int height = (int) (550 * zoom);
			if (height > screenSize.getHeight()) {
				height = (int) screenSize.getHeight();
			}
			int width = (int) (750 * zoom);
			if (width > screenSize.getWidth()) {
				width = (int) screenSize.getWidth();
			}

			java.awt.Dimension dimension = new java.awt.Dimension(width, height);
			j.setSize(dimension);
			j.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2);

			j.setVisible(true);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
		}
		*/
	}

	public void save(Comprobante comprobante) throws DataAccessException  {
		comprobanteDAO.save(comprobante);
	}

	public Comprobante getById(Long id) throws DataAccessException {
		return comprobanteDAO.getById(id);
	}

	public Comprobante getByUUID(String UUID) throws DataAccessException {
		return comprobanteDAO.getByUUID(UUID);
	}

	public Comprobante getBySerieFolioAndRFCEmisor(final String serie,
			final String folio, final String rfcEmisor) throws DataAccessException {
		return comprobanteDAO.getBySerieFolioAndRFCEmisor(serie, folio, rfcEmisor);
	}

	public List<Comprobante> getAll() throws DataAccessException {
		return comprobanteDAO.getAll();
	}

	@SuppressWarnings("rawtypes")
	public List getComprobantesByNegocio(Negocio negocio, 
			HashMap<String, Object> criterios, List<String> extras, int start, int end) throws DataAccessException {
		return comprobanteDAO.getComprobanteByNegocio(negocio, criterios, extras, start, end);
	}

	public void setTime(Calendar date, int hour, int min, int sec) throws DataAccessException {
		date.set(Calendar.HOUR, hour);
		date.set(Calendar.MINUTE, min);
		date.set(Calendar.SECOND, sec);
		date.set(Calendar.HOUR_OF_DAY, hour);
		date.set(Calendar.MILLISECOND, 0);
	}

	@SuppressWarnings("rawtypes")
	public List getComprobanteByAllFieldsReport(Negocio negocio, String toSearch, List<String> extras) throws DataAccessException {
		return comprobanteDAO.getComprobanteByAllFieldsReport(negocio, toSearch, extras);
	}
	
	public ArrayList<Object> getByUUIDLike(final String uUID, final Negocio negocio) throws DataAccessException {
		return comprobanteDAO.getByUUIDLike(uUID, negocio);
	}

	public List<Comprobante> getComprobantesBySeriesAndNumber(
			final Negocio negocio, final String serie, 
			final String folioInicial, final String folioFinal) throws DataAccessException {
		
		List<Comprobante> secondFilteredList = new ArrayList<Comprobante>();
		
		long numInicial = Long.valueOf(folioInicial);
		long numFinal = Long.valueOf(folioFinal);
		
		List<Comprobante> firstFilteredList = comprobanteDAO
			.getComprobantesBySerie(negocio, serie);
		
		for(Comprobante currentComprobante : firstFilteredList) {
			long tempNum = Long.valueOf(currentComprobante.getFolio());
			if(tempNum>=numInicial && tempNum<=numFinal) {
				secondFilteredList.add(currentComprobante);
			}
		}
		
		return secondFilteredList;
	}

	public void save(List<Comprobante> comprobantes) throws DataAccessException {
		comprobanteDAO.save(comprobantes);
	}
	
	public Comprobante getComprobanteBySerieyFolio(Negocio negocio,
			String serie, String folio) throws DataAccessException {
		return comprobanteDAO.getComprobanteBySerieyFolio(negocio, 
				serie, folio);
	}

	public List<Comprobante> getReport2010(Negocio negocio, Calendar fechaInicio, Calendar fechaFin) throws DataAccessException {
		return comprobanteDAO.getReport2010(negocio, fechaInicio, fechaFin);
	}

	public Comprobante getBySerieFolio(String serie, String folio, Negocio negocio) throws DataAccessException {
		return comprobanteDAO.getBySerieFolio(serie, folio, negocio);
	}

	public List<Object[]> findComprobanteByIdExterno(final Negocio negocio,
			final String idExterno) throws DataAccessException {
		return comprobanteDAO.findComprobanteByIdExterno(negocio, idExterno);
	}
}
